package sync;

import net.IClient;
import org.apache.log4j.Logger;
import proxy.IProxyFactory;
import proxy.InvocationHandlerImp;
import proxy.JdkProxyFactory;
import register.MethodInfo;
import register.RegisterManager;
import sendRecieveWrapper.ICalledResponseTypeWrapper;
import sendRecieveWrapper.ICallerResponseTypeWrapper;
import sendRecieveWrapper.SendRecieveManager;
import sync.ResponseManager.Response;

import java.lang.reflect.InvocationHandler;

public class RpcService implements IRpcService {
	private static final Logger log = Logger.getLogger(RpcService.class);


	private IClient client;
	private IProxyFactory proxyFactory= new JdkProxyFactory();
	private ResponseManager responseManager = new ResponseManager();
	private InvocationHandler invocationHandler;
	private RegisterManager registerManager = new RegisterManager();
	private SendRecieveManager sendRecieveManager = new SendRecieveManager();


	public RpcService(IClient client) {
		this.client = client;
		invocationHandler = new InvocationHandlerImp<>(client,responseManager,registerManager,sendRecieveManager);
	}

	@Override
	public <T> T rpcService(Class<T> cls) {
		return proxyFactory.getProxy(cls, invocationHandler);
	}

	public void recieveRequest(RpcRequest request)
	{
		MethodInfo methodInfo = registerManager.getMethod(request.getName());
		Throwable throwable=null;
		Object responseBody = null;
		try {
			responseBody = methodInfo.invoke(request.getArguments());
		}catch (Throwable e){
			throwable = e;
			log.error("rpcError",e);
		}
		//TODO 这里有疑问，如果异常理论应该是需要把异常返回回去的，但是游戏行业为了性能可以不用考虑返回
		if(!methodInfo.isNeedReturn())
			return;

		ICalledResponseTypeWrapper ICalledResponseTypeWrapper =	sendRecieveManager.getICalledResponseTypeWrapper(methodInfo.getReturnType());
		RpcResponse response = ICalledResponseTypeWrapper.afterRecieve(responseBody);
		response.setResponseId(request.getRequestId());
		response.setResponseBody(responseBody);
		response.setThrowable(throwable);
		client.sendRpcResponse(response);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void recieveResponse(RpcResponse response) {
		Response res  = responseManager.getResponse(response.getResponseId());
		//超时  或者 重复回调
		if(res==null)
		{
			log.error("收到回调，但是回调对象找不到,responseBody为:"+response.toString());
			return;
		}
		ICallerResponseTypeWrapper handler = res.getRpcHandler();
		if(response.getThrowable()!=null){
			handler.onExecption(response.getThrowable());
			return;
		}
		handler.afterRecieve(response.getResponseBody());
	}
}
